﻿using Common;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using EC3_6CLH.Model;
using Microsoft.Win32;
using NewDevice.TCPIP;
using Ookii.Dialogs.Wpf;
using System.Collections.ObjectModel;
using System.IO;
using TcpService;

namespace EC3_6CLH.ViewModel
{
    public partial class MainViewModel
    {
        #region DebugParam

        private EC3TcpClient _debugTcpClient;
        [ObservableProperty] private int _debugStationIndex;
        [ObservableProperty] private string _debugIp;
        [ObservableProperty] private string _debugParamKey;
        [ObservableProperty] private UInt16 _debugAxis;
        [ObservableProperty] private UInt16 _debugIndex;
        [ObservableProperty] private UInt16 _debugSubIndex;
        [ObservableProperty] private string _debugType;
        [ObservableProperty] private string _debugValue;
        [ObservableProperty] private string _reportPath;
        [ObservableProperty] private string _testConfigFilePath;

        private Int16 _debugTypeValue;
        private UInt16 _debugValueLen;
        public List<int> ListDebugStationIndex { get; set; } = new List<int>();
        public List<string> ListDebugType { get; set; } = new();
        public List<string> ListDebugParamKey { get; set; } = new();

        partial void OnDebugStationIndexChanged(int value)
        {
            DebugIp = Workstations[value - 1].Ip;
        }

        partial void OnDebugParamKeyChanged(string value)
        {
            var param = GlobalValue.TestConfig.FindInitParamByName(value);
            if (param != null)
            {
                DebugAxis = InitParam.Axis;
                DebugIndex = param.Index;
                DebugSubIndex = param.SubIndex;
                DebugType = param.Type;
                DebugValue = param.Data;
            }
        }

        partial void OnDebugTypeChanged(string value)
        {
            _debugTypeValue = InitParam.GetDataType(value);
            _debugValueLen = InitParam.GetDataLen(value);
        }

        private void InitDebug()
        {
            ListDebugStationIndex.Clear();
            for (int i = 0; i < 12; i++)
            {
                ListDebugStationIndex.Add(i + 1);
            }
            ListDebugParamKey.Clear();
            foreach (var item in GlobalValue.TestConfig.InitParams)
            {
                ListDebugParamKey.Add(item.Name);
            }
            ListDebugType.Clear();
            {
                ListDebugType.Add("U16");
                ListDebugType.Add("F32");
                ListDebugType.Add("I8");
                ListDebugType.Add("I16");
                ListDebugType.Add("U8");
                ListDebugType.Add("U32");
                ListDebugType.Add("I32");
            }
            DebugStationIndex = 1;
            DebugParamKey = ListDebugParamKey[0];

            ReportPath = GlobalValue.Config.ParamList["测试报告路径"];
            TestConfigFilePath = GlobalValue.Config.ParamList["当前机种配置文件路径"];
        }

        #endregion DebugParam

        #region Debug Function

        [RelayCommand]
        public void SaveConfig(string value)
        {
            try
            {
                GlobalValue.Config.ParamList["测试报告路径"] = ReportPath;
                GlobalValue.Config.ParamList["当前机种配置文件路径"] = TestConfigFilePath;
                GlobalValue.Config.SaveToFile("config.xlsx", "参数配置");

                LoadConfig();
                InitDebug();
                AppendLog("保存配置成功");
            }
            catch (Exception)
            {
                AppendLog("文件保存失败,请检查文件是否占用!");
                //AppendLog(ex.Message+"!");
            }
        }

        [RelayCommand]
        public void SelectFile(string value)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog
                {
                    Filter = "Excel Files (*.xlsx)|*.xlsx",
                    Title = "选择一个Excel文件",
                    InitialDirectory = Path.GetDirectoryName(TestConfigFilePath),
                };

                if (openFileDialog.ShowDialog() == true)
                {
                    string selectedFilePath = openFileDialog.FileName;
                    TestConfigFilePath = selectedFilePath;
                }
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public void SelectDirectory(string value)
        {
            try
            {
                var dialog = new VistaFolderBrowserDialog
                {
                    Description = "请选择文件夹",
                    UseDescriptionForTitle = true,
                    SelectedPath = ReportPath,
                    ShowNewFolderButton = true,
                };
                if (dialog.ShowDialog() == true)
                {
                    ReportPath = dialog.SelectedPath;
                }
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task PingAsync()
        {
            try
            {
                var task = PingChecker.ContinuousPing(DebugIp, TimeSpan.FromSeconds(3));
                await task;
                if (task.Result)
                {
                    AppendLog($"ping {DebugIp} successfully");
                }
                else
                {
                    AppendLog($"ping {DebugIp} failed");
                }
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ConnectAsync()
        {
            try
            {
                _debugTcpClient = new EC3TcpClient(DebugIp);
                await _debugTcpClient.ConnectAsync();
                AppendLog($"{DebugIp}连接成功");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public void Disconnect(object value)
        {
            try
            {
                _debugTcpClient.Disconnect();
                AppendLog("断开成功");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task WriteParamAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }
                await _debugTcpClient.Write(DebugAxis, DebugIndex, DebugSubIndex, _debugTypeValue, _debugValueLen, InitParam.GetValueByType(DebugValue, DebugType));
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadParamAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }
                var result = await _debugTcpClient.Read(DebugAxis, DebugIndex, DebugSubIndex, _debugTypeValue, _debugValueLen);

                AppendLog($"读值为{result}");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadSnAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }
                var task = _debugTcpClient.ReadSn();
                await task;
                AppendLog($"读值为{task.Result}");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadStdDiAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                var stdDI = "";
                for (int i = 0; i < 16; i++)
                {
                    var di = (UInt16)await _debugTcpClient.Read(18, 0x6001, (ushort)(0x01 + i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"));
                    stdDI += $"{di} ";
                }
                AppendLog(stdDI);
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadStdDoAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控

                var stdDO = "";
                for (int i = 0; i < 16; i++)
                {
                    var @do = (UInt16)await _debugTcpClient.Read(18, 0x7001, (ushort)(0x01 + i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"));

                    stdDO += $"{@do} ";
                }
                AppendLog(stdDO);
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task SetStdDoHighAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                await _debugTcpClient.SetStdDo(true);
                AppendLog("打开标准DO完成");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task SetStdDoLowAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                await _debugTcpClient.SetStdDo(false);
                AppendLog("关闭标准DO完成");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadExtDiAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                var extDI = "";
                for (int j = 0; j < 4; j++)
                {
                    for (int i = 0; i < 16; i++)
                    {
                        var di = (UInt16)await _debugTcpClient.Read(18, (ushort)(0x6010 + j), (ushort)(0x01 + i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"));
                        extDI += $"{di} ";
                    }
                }
                AppendLog(extDI);
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task ReadExtDoAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                var extDO = "";
                for (int j = 0; j < 4; j++)
                {
                    for (int i = 0; i < 16; i++)
                    {
                        var @do = (UInt16)await _debugTcpClient.Read(18, (ushort)(0x7010 + j), (ushort)(0x01 + i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"));
                        extDO += $"{@do} ";
                    }
                }

                AppendLog(extDO);
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task SetExtDoHighAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                await _debugTcpClient.SetExtDo(true);
                AppendLog("打开拓展DO完成");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        [RelayCommand]
        public async Task SetExtDoLowAsync()
        {
            try
            {
                if (_debugTcpClient == null)
                {
                    throw new Exception($"{DebugIp}设备未连接");
                }

                // 标准IO监控
                await _debugTcpClient.SetExtDo(false);
                AppendLog("关闭拓展DO完成");
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }

        #endregion Debug Function

        #region DEVICE

        private PqwIoTcp IoModule;

        #endregion DEVICE

        [ObservableProperty] private ObservableCollection<DiDoStatus> _diDoStatuses = new ObservableCollection<DiDoStatus>();

        private void IoStatusChanged(object sender, bool oldValue, bool newValue)
        {
            var io = sender as DiDoStatus;
#pragma warning disable CS8602
            if (!io.IsUpdatingFromBackend && io.IsDo)
            {
                try
                {
                    IoModule.SetOutputChannel(io.ChannelIndex, newValue);
                }
                catch (Exception ex)
                {
                    MyLog.Error(ex);
                    AppendLog(ex.Message + "!");
                }
            }
            else if (!io.IsDo && newValue && !oldValue)
            {
                _ = Workstations[io.ChannelIndex].StartTestAsync();
            }
#pragma warning restore CS8602
        }

        private async Task UpdateDiDo()
        {
            try
            {
                while (_isRunning)
                {
                    var output = IoModule.GetAllOutputStatus();
                    var input = IoModule.GetAllInputStatus();

                    foreach (var t in DiDoStatuses)
                    {
                        t.SetStatusFromBackend(t.IsDo ? output[t.ChannelIndex] : input[t.ChannelIndex]);
                    }

                    await Task.Delay(100);
                }
            }
            catch (Exception ex)
            {
                AppendLog(ex.Message + "!");
            }
        }
    }
}